<template>
  <div
    class="dh-select"
    :class="{
      [`dh-select--${props.size}`]: props.size,
      'is-disabled': props.disabled,
    }"
    @click="openOrcloseSelectList"
    @mouseenter="status.isHoverOption = true"
    @mouseleave="status.isHoverOption = false"
  >
    <Tooltip
      placement="bottom-start"
      visible
      ref="dropdown"
      :popper-options="popperOptions"
      @click-outside="selectList(false)"
    >
      <Input
        :readonly="!filterable || !isOpen"
        v-model="status.inputValue"
        :placeholder="computedPlaceholder"
        ref="input"
        @input="debounceFilter"
        @keydown.stop="handleKeyDown"
      >
        <template #suffix>
          <Icon
            icon="circle-xmark"
            v-if="showClear"
            class="dh-input__clear"
            @click.stop="cleareValue"
          ></Icon>
          <Icon
            v-else
            icon="angle-down"
            class="header-angle"
            :class="{ 'is-active': isOpen }"
          ></Icon>
        </template>
      </Input>
      <template #content>
        <div class="dh-select__loading" v-if="status.loading">
          <Icon icon="spinner" spin></Icon>
        </div>
        <div
          class="dh-select__nodata"
          v-else-if="filterable && filterOptions.length == 0"
        >
          no data
        </div>
        <ul class="dh-select__menu" v-else>
          <template v-for="(item, index) in filterOptions" :key="index">
            <li
              @click.stop="optionClick(item)"
              class="dh-select__menu-item"
              :class="{
                'is-disabled': item.disabled,
                'is-selected': status.selectedOption?.value === item.value,
                'is-highlighted':index === status.isHandleOption
              }"
              :id="`select-item-${item.value}`"
            >
              <RenderVnode
                :v-node="renderLabel ? renderLabel(item) : item.label"
              ></RenderVnode>
            </li>
          </template>
        </ul>
      </template>
    </Tooltip>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, computed, reactive, type Ref , inject } from "vue";
import Tooltip from "../Tooltip/Tooltip.vue";
import Input from "../Input/Input.vue";
import Icon from "../Icon/Icon.vue";
import { isFunction , debounce } from "lodash-es";
import type { DropdownInstance } from "../Dropdown/type";
import  { FormItemContextKey } from '@/components/Form/type'
import type {
  SelectEmits,
  SelectOptions,
  SelectProps,
  SelectStatus,
} from "./type";
import type { InputInstance } from "../Input/type";
import RenderVnode from "../conmon/RenderFun";
defineOptions({
  name: "DhSelect",
});
const findOption = (value: string | number) => {
  return props.options?.find((item) => item.value === value);
};
//接收的数据
const props = withDefaults(defineProps<SelectProps>(), {});
//自定义事件
const emits = defineEmits<SelectEmits>();
let timeout = computed(()=>props.remote?300:0)

let findop = findOption(props.modelValue!);
//收集的数据
let status = reactive<SelectStatus>({
  inputValue: findop ? findop.label : "",
  selectedOption: null,
  isHoverOption: false,
  loading: false,
  isHandleOption:-1
});
const popperOptions: any = {
  modifiers: [
    {
      name: "offset",
      options: {
        offset: [0, 9],
      },
    },
    {
      name: "sameWidth",
      enabled: true,
      fn: ({ state }: { state: any }) => {
        state.styles.popper.width = `${state.rects.reference.width}px`;
      },
      phase: "beforeWrite",
      requires: ["computeStyles"],
    },
  ],
};
//Dropdown实例
let dropdown = ref() as Ref<DropdownInstance>;
//input实例
let input = ref() as Ref<InputInstance>;
//监视数据
watch(
  () => props.modelValue,
  (newValue) => {
    findop = findOption(newValue!);
    status.inputValue = findop ? findop.label : "";
  }
);
//是否展开下拉菜单
let isOpen = ref<boolean>(false);
//是否展开下拉菜单
const selectList = (show: boolean) => {
  if (show) {
    if (props.filterable && status.selectedOption) {
      status.inputValue = "";
    }
    if (props.filterable && status.selectedOption) {
      filterOptionsFun(status.inputValue!);
    }
    isOpen.value = show;
    dropdown.value.show();
  } else {
    if (props.filterable && status.selectedOption) {
      status.inputValue = status.selectedOption?.label;
    }
    status.isHandleOption = -1
    isOpen.value = show;
    dropdown.value.hide();
  }
  emits("visible-change", show);
};
//是否显示清除按钮
const showClear = computed(() => {
  return (
    props.clearable &&
    status.inputValue &&
    !props.disabled &&
    status.isHoverOption &&
    status.selectedOption
  );
});
let computedPlaceholder = computed(() => {
  return props.filterable &&
    isOpen.value &&
    status.selectedOption &&
    !props.disabled
    ? status.selectedOption.label
    : props.placeholder;
});
// 表单校验
const formValidate = inject(FormItemContextKey)
const onValidate = (tirgger?:string)=>{
  formValidate?.validate(tirgger!)
}
//筛选后的options
let filterOptions = ref<SelectOptions[]>(props.options!);
watch(
  () => props.options,
  (newValue) => {
    filterOptions.value = newValue!;
  }
);
//筛选函数
const filterOptionsFun = async (search: string) => {
  if (!props.filterable) return;
  if (props.filterMethod && isFunction(props.filterMethod)) {
    filterOptions.value = props.filterMethod(search);
  } else if (
    props.remote &&
    props.remoteMethod &&
    isFunction(props.remoteMethod)
  ) {
    status.loading = true;
    try {
      filterOptions.value = await props.remoteMethod(search);
    } catch (error) {
      console.log(error);
    } finally {
      status.loading = false;
    }
  } else {
    filterOptions.value = props.options!.filter((item) =>
      item.label.includes(search)
    );
    status.isHandleOption = -1

  }
};
const onFilter = () => {
  filterOptionsFun(status.inputValue!);
};
const debounceFilter = debounce(()=>{
  onFilter();
}, timeout.value);
//点击事件
const openOrcloseSelectList = () => {

  //判断是否禁用
  if (props.disabled) return;
  //判断是否打开
  if (isOpen.value) {
    //打开就关闭
    selectList(false);
  } else {
    //关闭就打开
    selectList(true);
  }
};
//选项点击事件
const optionClick = (item: SelectOptions) => {
  if (item.disabled) return;
  status.inputValue = item.label;
  status.selectedOption = item;
  // filterOptions.value = props.options!
  //修改数据
 
  emits("update:modelValue", item.value);
  emits("change", item.value);
  //关闭下拉菜单
  selectList(false);
  input.value.ref.focus();
  onValidate('change')
};
//键盘打开或者关闭下拉菜单
const handleKeyDown = (e: KeyboardEvent) => {
  console.log(e.key);
  
    switch(e.key) {
      case "Enter":
     if(!isOpen.value) {
      selectList(true)
     }else {
      if(status.isHandleOption!>-1&&filterOptions.value[status.isHandleOption!]!==null) {
        optionClick(filterOptions.value[status.isHandleOption!])
      }
      selectList(false)
     }
      break;
      case "Escape":
      selectList(false)
      break;
      case "ArrowUp":
        if(filterOptions.value.length>0) {
          if(status.isHandleOption==-1|| status.isHandleOption==0) {
            status.isHandleOption = filterOptions.value.length-1
          }else {
           status.isHandleOption!-=1
          }
        }
        break;
      case "ArrowDown":
      if(filterOptions.value.length>0) {
          if(status.isHandleOption==-1|| status.isHandleOption==filterOptions.value.length-1) {
            status.isHandleOption = 0
          }else {
           status.isHandleOption!+=1
          }
        }
        break;
    }
}
//清除选中值
const cleareValue = () => {
  status.inputValue = "";
  status.selectedOption = null;
  emits("update:modelValue", "");
  emits("change", "");
  emits("clear");
  input.value.ref.focus();
};
</script>

<style scoped></style>
